home *** CD-ROM | disk | FTP | other *** search
- PROGRAM BList;
-
- { TURBO PASCAL SOURCE CODE LISTER AND BEGIN-END COUNTER PROGRAM }
-
- { Prints a listing to console or printer of a TURBO PASCAL source code with
- optional display of comment counter and begin/end counter, and also optional
- display skip of paper perforations. Accepts file name passed by CP/M or
- from operator input of file to list. }
-
- { This version of the code is specific to CP/M-80 because the GET_IN_FILE
- procedure looks for a parameter passed by CP/M at absolute location $80. The
- procedure could be modified for other operating systems, or not to accept
- passed parameters at all. }
-
- { I declare that this code is released to the PUBLIC DOMAIN as of July 1, 1984
- Phillip M. Nickell }
-
- { Modified Sept. 1, 1984 by Marvin Landis
- Record/end combination is now handled correctly. }
-
- VAR Buff1: STRING[135]; { Input line buffer }
- ListFil: TEXT; { Fib for LST: or CON: output }
- InFile: TEXT; { Fib for input file }
- BCount,KCount,LineCt: INTEGER; { Counters }
- Count_Be,PerfSkip: BOOLEAN; { Count begin/end and skip }
-
- CONST First: BOOLEAN = TRUE; { True when program is run }
-
- { To customize code for your printer and desires - adjust the next two items }
-
- MaxLine = 60; { max # of lines on page when in PERFSKIP mode }
- SkipLine = 2; { # of lines to skip at top of form }
-
- CR = #13;
- LF = #10;
- FF = #12;
-
- Procedure Clean; { Clears screen and positions cursor }
- BEGIN
- ClrScr;
- GoToXY(1,10);
- END;
-
- Procedure Lines(X: Integer); { Puts X amount of blank lines to output file }
- Var N: Integer;
- BEGIN
- For N:= 1 To X Do
- Writeln(ListFil);
- END;
-
- { GET_IN_FILE PROCEDURE : When program is first run, it will check for a file
- name passed by CP/M and will try to open that file. If no name is passed,
- it will ask operator for a file name to open. Proc will tell operator if
- file doesn't exist and will allow multiple retrys. On second and later
- executions, proc will not check for CP/M passed file name. In all cases
- proc will assume a file type of .PAS if file type is not specified. Exit
- from the program occurs when a null string is entered in response to a file
- name request. }
-
- Procedure Get_In_File; { Gets input file name }
- Var FNam: String[14]; { Input file name }
- Parm: String[14] Absolute $81; { Passed file name if any }
- ParmLth: Byte Absolute $80; { CP/M passed length of Parm }
- Existing: Boolean;
- BEGIN
- Repeat { Until file exists }
- If (ParmLth In [1..14]) And First Then
- FNam:= Copy(Parm,1,ParmLth - 1)
- Else Begin
- Clean;
- Write('Enter file name to list or <CR> to exit: ');
- Readln(FNam);
- End;
- If FNam = '' Then Halt;
- If Pos('.',FNam) = 0 Then
- FNam:= Concat(FNam,'.PAS'); { File default to .PAS type }
- First:= False;
- Assign(InFile,FNam);
- {$I-}
- Reset(InFile);
- {$I+}
- Existing:= (IOResult = 0);
- If Not Existing Then Begin
- Clean;
- Writeln('File does not exist.');
- Delay(700);
- End;
- Until Existing;
- END; { Get_In_File }
-
- { GET_OUT_FILE procedure : Asks operator to select output to console device
- or list device, and then assigns and resets a file control block to the
- appropriate device. 'C' or 'P' are the only correct responses, and
- multiple retrys are allowed. }
-
- Procedure Get_Out_File;
- Var C: Char;
- BEGIN
- Repeat { Until good selection }
- Clean;
- Write('Output listing to (C)onsole or (P)rinter? ');
- C:= UpCase(Chr(BDos(1)));
- Until C In ['C','P'];
- Writeln;
- If C = 'C' Then
- Assign(ListFil,'CON:')
- Else
- Assign(ListFil,'LST:');
- Reset(ListFil);
- END; { Get_Out_File }
-
- { GET_OPTIONS procedure : Asks operator if count of begin/end pairs is desired,
- and also if skip over paper perforations is desired. Proc will set or clear
- the Count_Be flag and the PerfSkip flag. }
-
- Procedure Get_Options;
- Var C: Char;
- BEGIN
- Repeat
- Clean;
- Write('Count of BEGIN/END pairs (Y/N)? ');
- C:= UpCase(CHR(BDOS(1)));
- Until C In ['Y','N'];
- If C = 'Y' Then Count_Be:= True
- Else Count_Be:= False;
- Repeat
- Clean;
- Write('Skip printer perforations (Y/N)? ');
- C:= UpCase(Chr(BDOS(1)));
- Until C In ['Y','N'];
- If C = 'Y' Then PerfSkip:= True
- Else PerfSkip:= False;
- END; { Get_Options }
-
- { SCAN_LINE procedure : Scans one line of Turbo Pascal source code looking
- for begin/end pairs, case/end pairs, literal fields and comment fields.
- BCount is begin/end and case/end counter. KCount is comment counter.
- Begin/case/ends are only valid outside of comment fields and literal
- constant fields (KCount = 0 and NOT LITERAL). Some of the code in this
- procedure appears at first glance to be repetitive and/or redundant, but
- was added to speed up the process of scanning each line of source code.
- The program now spits out listings much faster than a 160 cps printer. }
-
- Procedure Scan_Line;
- Var Literal: Boolean; { True if in literal field }
- Tmp: String[8]; { Temp work area }
- Buff2: String[135]; { Working line buffer }
- I: Integer;
- BEGIN
- Literal:= False;
- Buff2[0]:= Buff1[0]; { Copy input buffer into working buffer }
- For I:= 1 to Length(Buff1) Do
- Buff2[I]:= UpCase(Buff1[I]);
- Buff2:= Concat(' ',Buff2,' '); { Add on some working space }
- For I:= 1 to Length(Buff2) - 7 Do Begin
- Tmp:= Copy(Buff2,I,8);
- If Not Literal Then Begin
- If Tmp[1] In ['{','}','(','*'] Then Begin
- If (Tmp[1] = '{') Or (Copy(Tmp,1,2) = '(*') Then
- KCount:= Succ(KCount);
- If (Tmp[1] = '}') Or (Copy(Tmp,1,2) = '*)') then
- KCount:= Pred(KCount);
- End;
- End;
- If KCount = 0 Then Begin
- If Tmp[1] = Chr(39) Then Literal:= Not Literal;
- If Not Literal And (Tmp[2] In ['B','C','E','R']) Then Begin
- If (Copy(Tmp,1,7) = ' BEGIN ') Or (Copy(Tmp,1,6) = ' CASE ') Or
- (Tmp = ' RECORD ') Then Begin
- BCount:= Succ(BCount);
- I:= I + 5;
- End;
- If (Copy(Tmp,1,4) = ' END') And (Tmp[5] In ['.',' ',';']) Then Begin
- BCount:= Pred(BCount);
- I:= I + 4;
- End;
- End;
- End;
- End;
- END; { Scan_Line }
-
- BEGIN
- Repeat { Forever }
- Get_In_File;
- Get_Out_File;
- Get_Options;
- Lines(1);
- Linect:= 1;
- If Count_Be Then Begin
- KCount:= 0;
- BCount:= 0;
- Writeln(ListFil,' C B');
- End;
- While Not EOF(InFile) Do Begin
- Readln(InFile,Buff1);
- If Count_Be Then Begin
- Scan_Line;
- Writeln(ListFil,KCount:2,BCount:3,' ',Buff1);
- End Else
- Writeln(ListFil,Buff1);
- If PerfSkip Then Begin
- LineCt:= Succ(LineCt);
- If LineCt > MaxLine Then Begin
- Write(ListFil,FF);
- Lines(SkipLine);
- LineCt:= 1;
- If Count_Be Then Writeln(ListFil,' C B');
- End;
- End;
- End;
- Write(CR,LF,'Hit any key to continue...');
- BCount:= BDOS(1);
- Until False; { Exit is in Get_In_File procedure }
- END.
-